import datetime
from rest_framework import serializers
from .models import Orders, GasStationInfo, GunNos, OilInfo, ExpiryDatePrice
from core.tools.func_utils import funcUtils
from .client import get_czb_api, get_czb_api_by_czb_appkey
from django.conf import settings
from finance_c2c.local_settings import Config, ONLINE
from core.tools.func_utils import round_custom
from .utils import get_actual_time_price
from core.tools.CustomFieldsModelSerializer import DynamicFieldsModelSerializer
from .models import ApiChannel, ReceiptTicket, OrderTicket, GasFollow, ChannelPrice


# 继承czb接口类
class BaseSerializers(DynamicFieldsModelSerializer):
    channel = serializers.CharField(required=False, allow_null=True, label="渠道key", write_only=True, allow_blank=True)

    def validate_channel(self, channel):
        if not channel:
            channel = "youpinhuiyuan"
        czb_api = get_czb_api(channel)
        setattr(self, "czb_api", czb_api)
        return ApiChannel.objects.get(app_key=channel)


# 加油站信息
class GasStationSerializers(DynamicFieldsModelSerializer):
    class Meta:
        model = GasStationInfo
        fields = (
            "gasName", "gasType", "gasLogoSmall", "gasLogoBig", "gasAddress", "gasAddressLongitude",
            "gasAddressLatitude", "isInvoice")


class OilInfoSerializers(serializers.ModelSerializer):
    gs_station = GasStationSerializers(many=False, label="加油站信息")

    class Meta:
        model = OilInfo
        fields = ("oilNo", "gs_station")


class GunNosSerializers(serializers.ModelSerializer):
    oil = OilInfoSerializers(many=False, label="油号信息")

    class Meta:
        model = GunNos
        fields = ("gunNo", "oil")


# 订单查询/创建
class OrdersSerializers(BaseSerializers):
    id = serializers.IntegerField(read_only=True)
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    gas = serializers.PrimaryKeyRelatedField(label="加油站id（本地id）", queryset=GasStationInfo.objects.all(),
                                             write_only=True)
    gunNumber = serializers.IntegerField(label="油枪号", help_text="油枪号", write_only=True)
    amountGun = serializers.DecimalField(label="机显价格(用户输入价格)", help_text="机显价格(用户输入价格)", required=True,
                                         allow_null=False,
                                         max_digits=6, decimal_places=2, write_only=True)
    create_time = serializers.DateTimeField(read_only=True, label="创建时间", format=settings.API_DATETIME_FORMAT)
    result = serializers.SerializerMethodField(label="支付结果")
    order_type = serializers.IntegerField(read_only=True, label="订单类型")
    gas_info = serializers.SerializerMethodField(label="对应的加油站信息")
    payment = serializers.DecimalField(label="支付金额", max_digits=6, decimal_places=2, read_only=True)
    result_type = serializers.SerializerMethodField(label="支付结果标识")

    def get_result(self, instance):
        return instance.get_result_display()

    def get_gas_info(self, instance):
        kwargs = {"many": False, "context": self.context}
        return GasStationSerializers(instance.gas, **kwargs).data

    def validate_amountGun(self, amountGun):
        if ONLINE:
            # if amountGun < 50:
            #     raise serializers.ValidationError("订单金额不能小于50元")
            # else:
            #     return amountGun
            return amountGun
        else:
            return amountGun

    def get_result_type(self, instance):
        return instance.result

    def validate(self, attrs):
        gas_instance = attrs.pop("gas")
        gunNumber = attrs["gunNumber"]
        user = self.context["request"].user
        # 获取实时价格
        gun_price_info = get_actual_time_price(gas_instance.gasId, user.mobile, gunNumber, self.czb_api)
        if not isinstance(gun_price_info, dict):
            raise serializers.ValidationError(gun_price_info)
        amountGun = attrs["amountGun"]  # 机显金额
        priceGun = gun_price_info.get("priceGun")
        priceYfq = gun_price_info.get("priceYfq")
        oilName = gun_price_info.get("oilName")
        attrs["priceGun"] = priceGun
        attrs["amountGun"] = amountGun
        attrs["priceUnit"] = priceYfq
        attrs["gas"] = gas_instance
        attrs["user"] = user
        attrs["oilName"] = oilName
        attrs["czb_app_key"] = attrs["channel"].channelriseinprice.czb_key
        # 增加服务费
        server_fee = ChannelPrice.objects.get_server_fee(attrs["channel"], amountGun)
        attrs["server_fee"] = server_fee
        return attrs

    class Meta:
        model = Orders
        fields = ("channel", "gas", "payment", "gunNumber", "amountGun", "user", "create_time", "result",
                  "order_type", "gas_info", "id", "result_type")

    def get_czb_order(self, user, instance, gasId, gunNumber, validated_data, token):
        response = self.czb_api.create_orders(gasId, gunNumber, validated_data["amountGun"],
                                              validated_data["outerOrderId"],
                                              token)
        if response.get("code") == 200 or response.get("code") == "200":
            result = response.get("result")
            orderId = result.get("orderId")
            orderSn = result.get("orderSn")
            amountPay = result.get("amountPay")
            litre = result.get("litre")
            instance.orderSn = orderSn
            instance.orderId = orderId
            instance.payment_czb = amountPay  # 需要支付给车主邦金额
            instance.payment = amountPay + float(instance.server_fee)  # 用户实付金额
            instance.litre = litre
            now_time = datetime.datetime.now()
            instance.update_time = now_time
        elif response.get("code") == 10022 or response.get("code") == "10022":
            self.czb_api.platform_login(user.mobile)
            token = self.czb_api.get_token_from_mc(user.mobile)
            self.get_czb_order(user, instance, gasId, gunNumber, validated_data, token)  # 如果是token错误 调自己
        else:
            instance.result = response.get("code")
            instance.message = response.get("message")
            raise serializers.ValidationError(response.get("message"))
        instance.save()
        return instance

    def create(self, validated_data):
        validated_data["outerOrderId"] = funcUtils.unique_value  # 外部订单号
        instance = super(OrdersSerializers, self).create(validated_data)
        gunNumber = validated_data["gunNumber"]
        user = self.context["request"].user
        token = self.czb_api.get_token_from_mc(user.mobile)
        gasId = instance.gas.gasId
        instance = self.get_czb_order(user, instance, gasId, gunNumber, validated_data, token)
        return instance


# 订单详情
class OrderRetrieveSerializers(serializers.ModelSerializer):
    # gunNo = GunNosSerializers(read_only=True, label="加油站信息", many=False, help_text="加油站信息")
    pay_time = serializers.DateTimeField(read_only=True, label="支付时间", help_text="支付时间",
                                         format=settings.API_DATETIME_FORMAT)
    result_desc = serializers.SerializerMethodField(label="结果", help_text="结果")
    gas = GasStationSerializers(read_only=True, fields=("gasName", "gasAddress", "isInvoice"))
    gunNumber = serializers.SerializerMethodField(label="油枪号")
    oilName = serializers.SerializerMethodField(label="oilName")
    is_invoice = serializers.SerializerMethodField(label="是否已经开过票了")

    def get_result_desc(self, instance):
        return instance.get_result_display()

    def get_gunNumber(self, instance):
        if instance.order_type == 2:
            return ""
        if instance.gunNumber:
            return instance.gunNumber
        else:
            return instance.gunNo.gunNo

    def get_oilName(self, instance):
        if instance.order_type == 2:
            return ""
        if instance.oilName:
            return instance.oilName
        else:
            return instance.gunNo.oil.oilName

    def get_is_invoice(self, instance):
        if hasattr(instance, "orderticket") and instance.orderticket.serialNo:
            return True
        else:
            return False

    class Meta:
        model = Orders
        fields = ("id", "outerOrderId", "payment", "amountGun", "litre", "pay_time", "result",
                  "order_type", "result_desc", "oilName", "gunNumber", "gas", "is_invoice")


# 取消订单 /申请退款
class OrdersCancelSerializers(DynamicFieldsModelSerializer):
    result = serializers.ChoiceField(choices=Orders.orderStatus, label="订单状态", help_text="订单状态")

    def validate_result(self, attrs):
        if attrs == 101 or attrs == "101" or attrs == 5 or attrs == "5":
            return attrs
        else:
            raise serializers.ValidationError("取消订单传入参数错误")

    class Meta:
        model = Orders
        fields = ("result",)

    # def tl_refund(self, refund_amount, order_no, tl_pay_record_obj, out_refund_no):
    #     """
    #     通联退款
    #     :param refund_amount: 退款金额
    #     :param order_no: 支付时的订单号
    #     :param tl_pay_record_obj: 支付对象
    #     :param out_refund_no: 商户退款订单号
    #     :return:
    #     """
    #     order_datetime = tl_pay_record_obj.orderDatetime
    #
    #     pp_key_h5 = PublicPrivate.objects.get(company="tonglianqianbao", file_type=1, func_type="H5")
    #     h5_client = TLClient(pp_key_h5.private_file.path, pkcs1_rsa_public=pp_key_h5.public_file.path)
    #     response = h5_client.refund_api(refund_amount, order_no, order_datetime, out_refund_no)
    #     response["pay_record"] = tl_pay_record_obj
    #     if response.get("refundResult") == "20" or response.get("refundResult") == 20:
    #         # 成功
    #         TLRefundRecord.objects.create_refund(**response)
    #     else:
    #         TLRefundRecord.objects.create_refund(**response)
    #         raise serializers.ValidationError(response.get("ERRORMSG"))
    #
    # def wx_refund(self, total_fee, refund_fee, out_refund_no, out_trade_no):
    #     """
    #     微信退款
    #     :return:
    #     """
    #     notify_url = Config.host + "/shop/api/receive_refund"
    #     try:
    #         response = wx_pay.refund.apply(total_fee, refund_fee, out_refund_no, out_trade_no=out_trade_no,
    #                                        notify_url=notify_url)
    #     except WeChatPayException as e:
    #         print("%s" % e)
    #         raise serializers.ValidationError(e.errmsg)
    #     if response.get("result_code") != "SUCCESS":
    #         RefundRecord.objects.create_record_error(response, refund_fee, total_fee)
    #         raise serializers.ValidationError(response.get("return_msg"))
    #     response = self.wx_refund(total_fee, refund_fee, out_refund_no, out_trade_no)
    #     refund_obj = RefundRecord.objects.create_record(response)  # 微信退款记录

    def update(self, instance, validated_data):
        # validated_data["result"] = 101 # 订单取消代码
        now_time = datetime.datetime.now()
        czb_app_key = instance.czb_app_key
        czb_api = get_czb_api_by_czb_appkey(czb_app_key)
        if validated_data["result"] == 101 or validated_data["result"] == "101":
            token = czb_api.get_token_from_mc(self.context["request"].user.mobile)
            response = czb_api.cancel_order(instance.orderId, token)
            if response.get("code") == 200 or response.get("code") == "200":
                instance.result = validated_data["result"]
            elif response.get("message") == "订单不是未支付状态，不能取消订单":
                instance.result = validated_data["result"]
            else:
                message = response.get("message")
                instance.message = message
                instance.update_time = now_time
                instance.save()
                raise serializers.ValidationError(message)
        elif validated_data["result"] == 5 or validated_data["result"] == "5":  # 提交到车主邦申请退款
            token = czb_api.get_token_from_mc(self.context["request"].user.mobile)
            orderSn, payAmount, outOrderId = instance.orderSn, instance.payment_czb, instance.outerOrderId
            response = czb_api.order_refund(orderSn, int(payAmount * 100), outOrderId, token)
            if response.get("code") == 200 or response.get("code") == "200":  # 车主邦申请退款
                instance.result = 5  # 支付通道未退款,已经提交到车主邦申请退款
                instance.save()
            else:
                instance.message = response.get("message")
                instance.update_time = now_time
                instance.save()
                raise serializers.ValidationError(response.get("message"))
        instance.update_time = now_time
        instance.save()
        return instance


# 购买权益
class EquityCancelSerializers(serializers.ModelSerializer):
    supply_id = serializers.SerializerMethodField(label="订单id")  # 重命名
    expiry_date_id = serializers.IntegerField(help_text="有效期", label="有效期id", write_only=True)
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    channel = serializers.CharField(required=False, allow_null=True, label="渠道id", write_only=True)

    def validate(self, attrs):
        expiry_date_id = attrs["expiry_date_id"]
        expiry_date_instance = ExpiryDatePrice.objects.get(id=expiry_date_id)
        if ONLINE:
            attrs["payment"] = round_custom(expiry_date_instance.price / 100.0, 2)
            attrs["payment_czb"] = round_custom(expiry_date_instance.price / 100.0, 2)
        else:
            attrs["payment"] = 0.01  # 测试用
            attrs["payment_czb"] = 0.01  # 测试用
        attrs["order_type"] = 2
        return attrs

    def validate_channel(self, channel):
        if channel:
            try:
                return ApiChannel.objects.get(app_key=channel)
            except Exception as e:
                return ApiChannel.objects.get(app_key="youpinhuiyuan")
        else:
            return None

    def get_supply_id(self, instance):
        return instance.id

    class Meta:
        model = Orders
        fields = ("supply_id", "user", "expiry_date_id", "channel")


# 权益期限及价格
class ExpiryDatePriceSerializers(serializers.ModelSerializer):
    price = serializers.SerializerMethodField(label="价格", help_text="价格")
    old_price = serializers.SerializerMethodField(label="价格", help_text="价格")

    def get_price(self, instance):
        return instance.price / 100.0

    def get_old_price(self, instance):
        return instance.old_price / 100.0

    class Meta:
        model = ExpiryDatePrice
        fields = ("price", "month", "id", "old_price", "name")


# 直降金额
class DepreciateAmountSerializers(BaseSerializers):
    gasId = serializers.PrimaryKeyRelatedField(label="加油站id", help_text="加油站id", queryset=GasStationInfo.objects.all())
    oilNo = serializers.CharField(label="油号", help_text="油号")
    amountGun = serializers.CharField(label="用户输入金额", help_text="用户输入金额")

    def validate_amountGun(self, amountGun):
        if len(amountGun.split(".")[1]) != 2:
            raise serializers.ValidationError("amountGun需要保留两位小数")
        try:
            amountGun = float(amountGun)
        except Exception as e:
            raise serializers.ValidationError("amountGun数据格式错误")
        return "%.2f" % amountGun

    def create(self, validated_data):
        gas = validated_data["gasId"]
        oilNo = validated_data["oilNo"]
        amountGun = validated_data["amountGun"]
        user = self.context["request"].user
        response = self.czb_api.query_depreciate_amount(gas.gasId, oilNo, amountGun, user.mobile)
        code = response.get("code")
        if code != 200:
            raise serializers.ValidationError(response.get("message"))
        server_fee = ChannelPrice.objects.get_server_fee(validated_data["channel"], amountGun)
        response["server_fee"] = server_fee
        return response

    class Meta:
        model = Orders
        fields = ("channel", "gasId", "oilNo", "amountGun",)


# 发票信息
class ReceiptTicketSerializers(DynamicFieldsModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault(), write_only=True)
    title = serializers.ChoiceField(label="类型", choices=ReceiptTicket.ticketType)
    buyerTaxNo = serializers.CharField(label="购方纳税人识别号", allow_blank=True, required=False, allow_null=True)
    buyerName = serializers.CharField(label="购方单位名称", allow_blank=True, required=False, allow_null=True)
    buyerNamePeople = serializers.CharField(label="购方单位名称(个人)", allow_blank=True, required=False, allow_null=True)
    buyerAddressPhone = serializers.CharField(label="购方地址及电话", allow_blank=True, required=False, allow_null=True)
    buyerBankAccount = serializers.CharField(label="购方开户行及账号", allow_blank=True, required=False, allow_null=True)
    buyerEmail = serializers.CharField(label="购方客户邮箱", allow_blank=False, required=True, allow_null=False)

    def validate_title(self, title):
        if title == 0:
            buyerTaxNo = self.initial_data.get("buyerTaxNo")
            buyerName = self.initial_data.get("buyerName")
            if buyerTaxNo and buyerName:
                return title
            else:
                raise serializers.ValidationError("缺少必要信息")
        return title

    def create(self, validated_data):
        try:
            ticket_instance = ReceiptTicket.objects.get(user=self.context["request"].user, status=True, default=True)
            return super(ReceiptTicketSerializers, self).update(ticket_instance, validated_data)
        except Exception as e:
            return super(ReceiptTicketSerializers, self).create(validated_data)

    class Meta:
        model = ReceiptTicket
        exclude = ("default", "status", "invoiceContent",)


# 订单开票
class OrderTicketSerializers(DynamicFieldsModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault(), write_only=True)
    order = serializers.IntegerField(label="订单id", write_only=True)
    title = serializers.ChoiceField(label="类型", choices=ReceiptTicket.ticketType, read_only=True)
    buyerTaxNo = serializers.CharField(label="购方纳税人识别号", read_only=True)
    buyerName = serializers.CharField(label="购方单位名称", read_only=True)
    buyerNamePeople = serializers.CharField(label="购方单位名称(个人)", read_only=True)
    buyerAddressPhone = serializers.CharField(label="购方地址及电话", read_only=True)
    buyerBankAccount = serializers.CharField(label="购方开户行及账号", read_only=True)
    buyerEmail = serializers.CharField(label="购方客户邮箱", read_only=True)
    invoiceContent = serializers.IntegerField(label="开票类型", read_only=True)
    serialNo = serializers.CharField(label="开票流水号", read_only=True)

    def validate_order(self, order):
        try:
            order = Orders.objects.get(id=order, result=1)
        except Exception as e:
            raise serializers.ValidationError("订单错误")
        if hasattr(order, "orderticket") and order.orderticket.serialNo:
            raise serializers.ValidationError("此订单已经开过票了")
        return order

    def validate(self, attrs):
        user = self.context["request"].user
        ticket_info = ReceiptTicket.objects.get(user=user, status=True)
        title = ticket_info.title
        buyerTaxNo = ticket_info.buyerTaxNo
        buyerName = ticket_info.buyerName
        buyerNamePeople = ticket_info.buyerNamePeople
        buyerAddressPhone = ticket_info.buyerAddressPhone
        buyerBankAccount = ticket_info.buyerBankAccount
        buyerEmail = ticket_info.buyerEmail
        invoiceContent = ticket_info.invoiceContent
        attrs["title"] = title
        attrs["buyerTaxNo"] = buyerTaxNo
        if title == 1:
            attrs["buyerName"] = buyerNamePeople
        else:
            attrs["buyerName"] = buyerName
        attrs["buyerAddressPhone"] = buyerAddressPhone
        attrs["buyerBankAccount"] = buyerBankAccount
        attrs["buyerEmail"] = buyerEmail
        attrs["invoiceContent"] = invoiceContent
        order = attrs["order"]
        attrs["orderId"] = order.orderId
        czb_api = get_czb_api(order.channel.app_key)
        token = czb_api.get_token_from_mc(user.mobile)
        response = czb_api.gas_insert(token, **attrs)
        if response.get("code") == 200 or response.get("code") == "200":
            del attrs["orderId"]
            attrs["serialNo"] = response.get("result").get("serialNo")
            return attrs
        else:
            raise serializers.ValidationError(response.get("message"))

    class Meta:
        model = OrderTicket
        fields = "__all__"


# 加油站关注
class GasFollowSerializer(DynamicFieldsModelSerializer):
    gas_id = serializers.IntegerField(label="加油站id", write_only=True)
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    price = serializers.DecimalField(label="价格", max_digits=6, decimal_places=2)
    oilNo = serializers.IntegerField(label="油号")

    class Meta:
        model = GasFollow
        fields = ("id", "gas_id", "user", "price", "oilNo",)


# 后台订单
class OrdersSerializer(DynamicFieldsModelSerializer):
    channel_name = serializers.SerializerMethodField(label="渠道名称", help_text="渠道名称")
    out_trade_no = serializers.SerializerMethodField(label="订单号", help_text="渠道名称", read_only=True)
    order_time = serializers.SerializerMethodField(label="支付时间", help_text="支付时间")
    refund_time = serializers.SerializerMethodField(label="退款时间", help_text="退款时间")
    payment = serializers.CharField(label="支付金额(加油费+服务费)", help_text="支付金额(加油费+服务费)", read_only=True)
    desc_pay_type = serializers.SerializerMethodField(label="支付方式", help_text="支付方式", read_only=True)
    payment_czb = serializers.CharField(label="支付车主邦费用", help_text="支付车主邦费用", read_only=True)
    result_desc = serializers.SerializerMethodField(label="订单状态描述", help_text="订单状态描述")

    def get_order_time(self, instance):
        if instance.pay_time:
            return instance.pay_time.strftime("%Y-%m-%d %H:%M:%S")
        else:
            return ""

    # 退款时间
    def get_refund_time(self, instance):
        if instance.refund:
            if instance.refund.create_time:
                return instance.refund.create_time.strftime("%Y-%m-%d %H:%M:%S")
            else:
                return ""
        else:
            return ""

    def get_channel_name(self, instance):
        return instance.channel.name

    def get_pay_type_desc(self, instance):
        return instance.get_pay_type_display()

    def get_result_desc(self, instance):
        return instance.get_result_display()

    def get_desc_pay_type(self, instance):
        return instance.get_pay_type_display()

    def get_out_trade_no(self, instance):
        if instance.out_trade_no:
            return instance.out_trade_no
        else:
            return ""

    class Meta:
        model = Orders
        fields = ("channel_name", "result_desc", "out_trade_no", "order_time", "payment", "desc_pay_type",
                  "bank_server_fee_value", "payment_czb", "server_fee", "refund_time")


class OrdersTotalSerializer(DynamicFieldsModelSerializer):
    class Meta:
        model = Orders
        fields = ("channel_name",)


# channel
class APIChannelSerializers(DynamicFieldsModelSerializer):
    class Meta:
        model = ApiChannel
        fields = ("name", "id", "pay_type")
